package middleware

import (
	"net/http"
	"strings"

	"database/sql"

	"gitee.com/hp-huiw/family-expense-api/internal/security"
	"gitee.com/hp-huiw/my-go-core/date"
	"gitee.com/hp-huiw/my-go-core/errorcode"
	libsecurity "gitee.com/hp-huiw/my-go-core/security"
	"gitee.com/hp-huiw/my-go-core/servercode"
	"gitee.com/hp-huiw/my-go-core/util"
	"github.com/gin-gonic/gin"
)

// Checks on access token to see if it is a valid one and does not expire yet.
// Also checks on url access permission.
func AuthMiddleware(ctx *gin.Context) {
	c := ctx.Request.Context()
	urlFullPath := strings.TrimSpace(ctx.FullPath())

	if !util.IsEmptyString(urlFullPath) {
		var value, _ = ctx.Get(DatabaseStateKey)
		db := value.(*sql.DB)

		requestMethod := ctx.Request.Method
		authorizationHeader := strings.TrimSpace(ctx.GetHeader(util.HttpHeaderAuthorization))
		userActiveTokenManagerRepository := security.NewUserActiveTokenManagerRepository(db)
		requestMapQuery := security.NewSecurityRequestMapQuery(db)
		granted := libsecurity.CheckAuthorization(c, requestMethod, urlFullPath, authorizationHeader, userActiveTokenManagerRepository, requestMapQuery)

		// If user was authenticated but token is no longer valid or user is not granted for current url 401 code will be sent.
		if !granted {
			ctx.AbortWithStatusJSON(http.StatusUnauthorized, libsecurity.HandlerErrorResponse{
				Error:     servercode.ServerCodeUnauthorized,
				Message:   errorcode.ErrorUserAccountNotAuthorized,
				Path:      urlFullPath,
				Status:    http.StatusUnauthorized,
				Success:   false,
				Timestamp: date.GetCurrentDate().Unix(),
			})
		}
	}
}
